Jetpack DataStore 是一種數據存儲解決方案,允許您使用協議緩衝區存儲鍵值對或類型化物件。DataStore使用Kotlin協程和Flow以異步、一致的事務方式存儲數據。
如果您當前在使用"SharedPreferences"存儲數據,請考慮遷移到DataStore。
注意! 如果需要支持大型或複雜的數據、部分更新、參照完整性,請考慮使用"Room",而不是DataStore。
| 功能 | SharedPreferences(SP) | Preferences DataStore | Proto DataStore | 
|---|---|---|---|
| 異步API | ✔️(僅在使用listener讀取值的修改時) | ✔️(通過Flow) | ✔️(通過Flow) | 
| 同步API | ✔️(但在UI線程調用不安全) | ❌ | ❌ | 
| UI線程調用安全 | ❌ | ✔️(在內部將操作移至Dispatchers.IO) | 
✔️(在內部將操作移至Dispatchers.IO) | 
| 可以發出異常信號 | ❌ | ✔️ | ✔️ | 
| 避免運行時異常 | ❌ | ✔️ | ✔️ | 
| 具備事務處理 | ❌ | ✔️ | ✔️ | 
| 處理數據遷移 | ❌ | ✔️(遷移至SP) | ✔️(遷移至SP) | 
| 型別安全 | ❌ | ❌ | ✔️(使用Protocal Buffers) | 
// Preferences DataStore (SharedPreferences like APIs)
dependencies {
    implementation "androidx.datastore:datastore-preferences:1.0.0"
    // 可選 - 支持RxJava2
    implementation "androidx.datastore:datastore-preferences-rxjava2:1.0.0"
    // 可選 - 支持RxJava3
    implementation "androidx.datastore:datastore-preferences-rxjava3:1.0.0"
}
plugins {
    ...
    id 'com.google.protobuf' version '0.8.12' apply false
}
plugins {
    ...
    id "com.google.protobuf"
}
// Typed DataStore (Typed API surface, such as Proto)
dependencies {
    implementation "androidx.datastore:datastore:1.0.0"
    implementation "com.google.protobuf:protobuf-javalite:3.14.0"
    // 可選 - 支持RxJava2
    implementation "androidx.datastore:datastore-rxjava2:1.0.0"
    // 可選 - 支持RxJava3 
    implementation "androidx.datastore:datastore-rxjava3:1.0.0"
}
protobuf {
    protoc {
        // 這裡設置的版本要和implementation "protobuf-javalite"的版本一致
        artifact = "com.google.protobuf:protoc:3.14.0"
    }
    generateProtoTasks {
        all().each { task ->
            task.builtins {
                java {
                    option "lite"
                }
            }
        }
    }
}
步驟:
MyDataStore.java
// 定義DataStore的文件名稱
private static final String FILE_NAME = "MY_APP";
// 聲明MyDataStore存儲數據的KEY鍵
public final static Preferences.Key<String> NAME_KEY = PreferencesKeys.stringKey("name");
public final static Preferences.Key<Integer> AGE_KEY = PreferencesKeys.intKey("age");
private static RxDataStore<Preferences> dataStore;
MyDataStore.java
public MyDataStore(Context context) {
    if (dataStore == null) {
        dataStore = new RxPreferenceDataStoreBuilder(context, /*name=*/ FILE_NAME).build();
    }
};
MyDataStore.java
/**
 * 寫入數據
 */
public <T> void putValue(Preferences.Key<T> key, T value) {
    dataStore.updateDataAsync(new Function<Preferences, Single<Preferences>>() {
        @Override
        public Single<Preferences> apply(Preferences preferences) throws Throwable {
            MutablePreferences mutablePreferences = preferences.toMutablePreferences();
            mutablePreferences.set(key, value);
            Log.e("DataStore_Demo", "寫入數據__" + key + "->" + value);
            return Single.just(mutablePreferences);
        }
    });
}
/**
 * 獲取數據
 */
public <T> T getValue(Preferences.Key<T> key) {
    Flowable<T> value = dataStore.data().map(new Function<Preferences, T>() {
        @Override
        public T apply(Preferences preferences) throws Throwable {
            return preferences.get(key);
        }
    });
    return value.blockingFirst();
}
MainActivity.java
MyDataStore dataStore = new MyDataStore(/*context=*/this);
// 寫入數據
dataStore.putValue(MyDataStore.NAME_KEY, "Chen");
dataStore.putValue(MyDataStore.AGE_KEY, 66);
// 讀取數據
String name = dataStore.getValue(MyDataStore.NAME_KEY);
Integer age = dataStore.getValue(MyDataStore.AGE_KEY);
Log.d("DataStore_Demo", "讀取數據__" + "name:" + name + ", age:" + age);
這篇明天在介紹, (補上連結 https://ithelp.ithome.com.tw/articles/10307040 )